package threadPool;

import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;

/**
 * @author: 李德才
 * @description:
 * @create: 2020-12-20 17:01
 **/


/**
 * RecursiveAction 没有返回值
 * RecursiveTask  有返回值
 */
public class T13_ForkJoinPool {


    /**
     * ForkJoinPool 其主旨是将大任务分成若干小任务，
     * 之后再并行对这些小任务进行计算，
     * 最终汇总这些任务的结果,得到最终的结果。
     * 其广泛用在java8的stream中
     */

    static int[] nums = new int[1000000];
    static final int MAX_NUM = 50000;
    static Random random = new Random();

    static {
        for (int i = 0; i < nums.length; i++) {
            nums[i] = random.nextInt(100);
        }
    }

    /**
     * 流式计算
     */
    public void streamSum() {
        for (int i = 0; i < nums.length; i++) {
            nums[i] = random.nextInt(100);
        }
        System.out.println(" stream ====> " + Arrays.stream(nums).sum());
    }


    /**
     * RecursiveAction extends ForkJoinTask<Void>
     * 没有返回值
     */
    static class ForkJoinAdd extends RecursiveAction {
        private int startNumber;
        private int endNumber;

        public ForkJoinAdd(int startNumber, int endNumber) {
            this.startNumber = startNumber;
            this.endNumber = endNumber;
        }

        @Override
        protected void compute() {
            if (endNumber - startNumber <= MAX_NUM) {
                long sum = 0L;
                for (int i = startNumber; i < endNumber; i++) sum += nums[i];
                System.out.println("from:" + startNumber + " to:" + endNumber + " = " + sum);
            }
            int middle = startNumber + (endNumber - startNumber) / 2;
            ForkJoinAdd forkJoinAdd1 = new ForkJoinAdd(startNumber, middle);
            ForkJoinAdd forkJoinAdd2 = new ForkJoinAdd(middle, endNumber);
            forkJoinAdd1.fork();
            forkJoinAdd2.fork();
        }
    }


    /**
     * public abstract class RecursiveTask<V> extends ForkJoinTask<V>
     * 有返回值
     */
    static class ForkJoinAddRet extends RecursiveTask<Long> {
        private static final long serialVersionUID = 1L;
        private int startNumber;
        private int endNumber;

        public ForkJoinAddRet(int startNumber, int endNumber) {
            this.startNumber = startNumber;
            this.endNumber = endNumber;
        }

        @Override
        protected Long compute() {
            if (endNumber - startNumber <= MAX_NUM) {
                long sum = 0L;
                for (int i = startNumber; i < endNumber; i++) sum += nums[i];
                return sum;
            }
            int middle = startNumber + (endNumber - startNumber) / 2;
            ForkJoinAddRet forkJoinAdd1 = new ForkJoinAddRet(startNumber, middle);
            ForkJoinAddRet forkJoinAdd2 = new ForkJoinAddRet(middle, endNumber);
            forkJoinAdd1.fork();
            forkJoinAdd2.fork();
//            计算并相加结果
            return forkJoinAdd1.join() + forkJoinAdd2.join();
        }
    }


    public static void main(String[] args) throws IOException {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
//        ForkJoinAdd forkJoinAdd = new ForkJoinAdd(0, nums.length);
//        forkJoinPool.execute(forkJoinAdd);
        //       System.in.read();
        ForkJoinAddRet forkJoinAddRet = new ForkJoinAddRet(0, nums.length);
        forkJoinPool.execute(forkJoinAddRet);
        Long join = forkJoinAddRet.join();
        System.err.println(join);

    }
}
